#include "test-module-frame-format.h"
#include "test-module-external-interface.h"

extern testModuleExternalInterface_t testModuleExternalInterface;

TestModuleFrameFormat::TestModuleFrameFormat()
{
    //初始化接收指令数据指针
    callback_func = NULL;
    //初始化缓存数组
    memset(data_buffer, 0, sizeof(data_buffer));
    memset(save_buffer, 0, sizeof(save_buffer));
    //初始化保存数据长度
    save_data_length = 0;
}

int TestModuleFrameFormat::highConvertToLow(void *data_out, void *data_in, uint16_t length)
{
    //判断入参合法性
    if((NULL == data_in) || (NULL == data_out))
    {
        return -1;
    }

    uint8_t  src_data[length];
    uint8_t  tmp_data[length];

    memcpy(src_data, data_in, length);
    for(int i = 0; i < length; i++)
    {
        tmp_data[i] = src_data[length - i - 1];
    }
    memcpy(data_out, tmp_data, length);

    return 0;
}

uint16_t TestModuleFrameFormat::calcCrc16(const uint8_t *buffer, uint32_t size, uint16_t crc)
{
    if (NULL != buffer && size > 0) {
        while (size--) {
            crc = (crc >> 8) | (crc << 8);
            crc ^= *buffer++;
            crc ^= ((unsigned char) crc) >> 4;
            crc ^= crc << 12;
            crc ^= (crc & 0xFF) << 5;
        }
    }
    return crc;
}

void TestModuleFrameFormat::register_recv_command_data_callback(std::function<void(TestModuleFrameContent)> callback)
{
    callback_func = callback;
}

int TestModuleFrameFormat::frame_analysis_function(void *data, unsigned int length)
{
    int ret;
    unsigned char  frame_flag       = 0;
    unsigned char  from             = 0;
    unsigned char  to               = 0;
    unsigned char  command_id       = 0;
    unsigned short data_length      = 0;
    unsigned short check_sum_cal    = 0;
    unsigned short check_sum_read   = 0;
    unsigned char  temp_buffer[FRAME_BUFFER_LENGTH_MAX] = {0};
    unsigned short temp_data_length = 0;

    if((data == NULL) || (length > FRAME_BUFFER_LENGTH_MAX))
    {
        return -1;
    }else
    {
        memcpy(temp_buffer, save_buffer, save_data_length);     //拷贝上一次未解析完数据
        temp_data_length  = save_data_length + length;          //计算要解析的数据总长度
        memcpy(&temp_buffer[save_data_length], data, length);   //拷贝这一次读取到的所有数据
    }

    for(int i = 0; i < temp_data_length; i++)
    {
        if(temp_buffer[i] == FRAME_FLAG)//查找帧头标志位
        {
            if((temp_data_length - i) >= FRAME_HEADER_LENGTH)//判断剩余长度是否够解析帧头内容
            {
                from        = temp_buffer[i + FRAME_FROM_INDEX];
                to          = temp_buffer[i + FRAME_TO_INDEX];
                command_id  = temp_buffer[i + FRAME_COMMAND_ID_INDEX];
                highConvertToLow(&data_length, &temp_buffer[i + FRAME_DATA_LENGTH_INDEX], sizeof(data_length));

                if((data_length < FRAME_BUFFER_LENGTH_MAX) && (from == 0x08) && (to == 0x04))//判断读取到的数据长度是否有效，以及来源与目的是否是副板到主板
                {
                    if((FRAME_TOTAL_LENGTH(data_length) + i) <= temp_data_length)//判断读取数据是否够一整帧
                    {
                        memcpy(data_buffer, &temp_buffer[i], FRAME_TOTAL_LENGTH(data_length));//保存一整帧数据
                        save_data_length = temp_data_length - FRAME_TOTAL_LENGTH(data_length);//剩余数据下回解析
                        memcpy(save_buffer, &temp_buffer[FRAME_TOTAL_LENGTH(data_length) + i], save_data_length);//剩余数据下回解析
                        //计算校验值
                        check_sum_cal  = calcCrc16(data_buffer, FRAME_CHECK_DATA_LENGTH(data_length), CHECKSUM_INIT_VALUE);
                        highConvertToLow(&check_sum_read, &data_buffer[FRAME_CHECKSUM_INDEX(data_length)], sizeof(check_sum_read));
                        if(check_sum_cal == check_sum_read)//判断校验结果与校验位数据是否一致
                        {
                            printf("接收一帧数据！\n");
                            if(NULL != callback_func)
                            {
                                TestModuleFrameContent frame_content;

                                frame_content.flag          = FRAME_FLAG;
                                frame_content.from          = from;
                                frame_content.to            = to;
                                frame_content.command_id    = command_id;
                                frame_content.data_length   = data_length;
                                frame_content.data          = new uint8_t(data_length);
                                memcpy(frame_content.data, &data_buffer[FRAME_DATA_START_ADDR_INDEX], data_length);
                                frame_content.check_code    = check_sum_read;
                                
                                callback_func(frame_content);
                            }
                            break;
                        }else
                        {
                            //校验失败
                            if(TEST_LOG_FLAG)
                            {
                                printf("校验失败：%04x , %04x\n", check_sum_cal, check_sum_read);
                            }
                        }
                    }else
                    {
                        //数据不完整，继续等待
                        save_data_length = temp_data_length;
                        memcpy(save_buffer, temp_buffer, temp_data_length);
                        if(TEST_LOG_FLAG)
                        {
                            printf("不够解析整帧，数据不完整，继续等待，i = %d, length = %d\n", i, temp_data_length);
                        }
                        break;
                    }
                }else
                {
                    //数据错误
                    if(TEST_LOG_FLAG)
                    {
                        printf("数据长度：%d，from：%02x，to：%02x\n", data_length);
                    }
                }
            }else
            {
                //数据不完整，继续等待
                save_data_length = temp_data_length;
                memcpy(save_buffer, temp_buffer, temp_data_length);
                break;
            }
        }else
        {
            
        }
    }

    return ret;
}

int TestModuleFrameFormat::framePackageFunction(void *data_in, uint16_t length)
{
    int ret;
    uint8_t  send_buffer[256] = {0};
    uint16_t data_length = 0;
    uint16_t check_sum = 0;

    //判断传入参数
    if((data_in == NULL) && (length != 0))
    {
        return -1;
    }
    //填充帧内容
    send_buffer[0] = 0xFE;//帧头标准
    send_buffer[1] = 0x04;//从主板
    send_buffer[2] = 0x08;//发往上位机
    send_buffer[3] = 0xFF;//指令
    //写入数据长度
    highConvertToLow(&send_buffer[4], &length, sizeof(length));
    //写入数据内容
    memcpy(&send_buffer[6], data_in, length);//有效数据
    //计算校验值
    check_sum = calcCrc16(send_buffer, length + 6, 0xA1B2);
    //写入校验值
    highConvertToLow(&send_buffer[length + 6], &check_sum, sizeof(check_sum));

    if(testModuleExternalInterface.test_module_send_f != NULL)
    {
        ret = testModuleExternalInterface.test_module_send_f(send_buffer, length + 8);
    }else
    {
        ret = -1;
    }

    return ret;
}
